#include "dma.h"

extern uint8_t gDATABUF[DATA_BUF_SIZE];

static uint8_t ssp_rtemp = 0;
static uint8_t ssp_wtemp = 0x55;
// Terminal Counter flag for Channel 0
__IO uint32_t Channel0_TC;

// Error Counter flag for Channel 0
__IO uint32_t Channel0_Err;

// Terminal Counter flag for Channel 1
__IO uint32_t Channel1_TC;

// Error Counter flag for Channel 1
__IO uint32_t Channel1_Err;

void GPDMA_setup(void)
{
	GPDMA_Init();
	GPDMA_Channel_CFG_Type GPDMACfg;
    /* Configure GPDMA channel 0 -------------------------------------------------------------*/
    /* DMA Channel 0 */
  GPDMACfg.ChannelNum = 0;
	// Source memory
	GPDMACfg.SrcMemAddr = (uint32_t)&ssp_wtemp;
	// Destination memory - Not used
	GPDMACfg.DstMemAddr = 0;
	// Transfer size
	GPDMACfg.TransferSize = 0;
	// Transfer width - not used
	GPDMACfg.TransferWidth = 0;
	// Transfer type
	GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_M2P;
	// Source connection - unused
	GPDMACfg.SrcConn = 0;
	// Destination connection
	GPDMACfg.DstConn = GPDMA_CONN_SSP0_Tx;
	// Linker List Item - unused
	GPDMACfg.DMALLI = 0;
	// Setup channel with given parameter
	GPDMA_Setup(&GPDMACfg);

	/* Reset terminal counter */
	Channel0_TC = 0;
	/* Reset Error counter */
	Channel0_Err = 0;


    /* Configure GPDMA channel 1 -------------------------------------------------------------*/
    /* DMA Channel 1 */
	GPDMACfg.ChannelNum = 1;
	// Source memory - not used
	GPDMACfg.SrcMemAddr = 0;
	// Destination memory - Not used
	GPDMACfg.DstMemAddr = (uint32_t)&ssp_rtemp;
	// Transfer size
	GPDMACfg.TransferSize = 0;
	// Transfer width - not used
	GPDMACfg.TransferWidth = 0;
	// Transfer type
	GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_P2M;
	// Source connection
	GPDMACfg.SrcConn = GPDMA_CONN_SSP0_Rx;
	// Destination connection - not used
	GPDMACfg.DstConn = 0;
	// Linker List Item - unused
	GPDMACfg.DMALLI = 0;
	// Setup channel with given parameter
	GPDMA_Setup(&GPDMACfg);

	/* Reset terminal counter */
	Channel1_TC = 0;
	/* Reset Error counter */
	Channel1_Err = 0;

}

void dma_wwch(uint8_t *data,uint16_t len)
{
	LPC_GPDMA->DMACIntTCClear   |= 0x01;                              
	LPC_GPDMA->DMACIntErrClr    |= 0x01; 
	LPC_GPDMACH0->DMACCLLI = 0;                                                                                        
	LPC_GPDMACH0->DMACCControl    =  ((len)&0x0fff)|(1 << 26)|(0x80000000);            
	LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)data;             
	LPC_GPDMACH0->DMACCDestAddr= 0x40088008;  
	
	LPC_GPDMA->DMACIntTCClear   |= 0x02;                               
	LPC_GPDMA->DMACIntErrClr    |= 0x02;    
	LPC_GPDMACH1->DMACCLLI = 0;                  
	LPC_GPDMACH1->DMACCControl    =  ((len)&0x0fff)|(0x80000000);                    
	LPC_GPDMACH1->DMACCSrcAddr = 0x40088008;             
	LPC_GPDMACH1->DMACCDestAddr= (uint32_t)&ssp_rtemp;   

	SSP_DMACmd (LPC_SSP0, SSP_DMA_RX, ENABLE);
	SSP_DMACmd (LPC_SSP0, SSP_DMA_TX, ENABLE);

	LPC_GPDMACH0->DMACCConfig |= GPDMA_DMACCxConfig_E;
	LPC_GPDMACH1->DMACCConfig |= GPDMA_DMACCxConfig_E;
	while((!Channel0_TC)||(!Channel1_TC));
	Channel0_TC = 0;
	Channel1_TC = 0;
}
void dma_rrch(uint8_t *data,uint16_t len)
{
	LPC_GPDMA->DMACIntTCClear   |= 0x01;                                
	LPC_GPDMA->DMACIntErrClr    |= 0x01; 
	LPC_GPDMACH0->DMACCLLI = 0;                                                                                                  
	LPC_GPDMACH0->DMACCControl    =  ((len)&0x0fff)|(0x80000000);            
	LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&ssp_wtemp;             
	LPC_GPDMACH0->DMACCDestAddr= 0x40088008;  
	
	LPC_GPDMA->DMACIntTCClear   |= 0x02;                               
	LPC_GPDMA->DMACIntErrClr    |= 0x02;    
	LPC_GPDMACH1->DMACCLLI = 0;                                                                                             
	LPC_GPDMACH1->DMACCControl    =  ((len)&0x0fff)| (1<<27)|(0x80000000);                     
	LPC_GPDMACH1->DMACCSrcAddr = 0x40088008;             
	LPC_GPDMACH1->DMACCDestAddr= (uint32_t)data;   
	
	SSP_DMACmd (LPC_SSP0, SSP_DMA_TX, ENABLE);
	SSP_DMACmd (LPC_SSP0, SSP_DMA_RX, ENABLE);
	
	
	LPC_GPDMACH0->DMACCConfig |= GPDMA_DMACCxConfig_E;
	LPC_GPDMACH1->DMACCConfig |= GPDMA_DMACCxConfig_E;
	while((!Channel0_TC)||(!Channel1_TC));
	Channel0_TC = 0;
	Channel1_TC = 0;
}

void DMA_IRQHandler (void)
{
	// check GPDMA interrupt on channel 0
	if (GPDMA_IntGetStatus(GPDMA_STAT_INT, 0)){
		// Check counter terminal status
		if(GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 0)){
			// Clear terminate counter Interrupt pending
			GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);
				Channel0_TC++;
		}
		// Check error terminal status
		if (GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 0)){
			// Clear error counter Interrupt pending
			GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 0);
			Channel0_Err++;
		}
	}
	// check GPDMA interrupt on channel 1
	if (GPDMA_IntGetStatus(GPDMA_STAT_INT, 1)){
		// Check counter terminal status
		if(GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 1)){
			// Clear terminate counter Interrupt pending
			GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 1);
				Channel1_TC++;
		}
		// Check error terminal status
		if (GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 1)){
			// Clear error counter Interrupt pending
			GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 1);
			Channel1_Err++;
		}
	}
}
